using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using Cinemachine;



struct PlayerInput{
    public bool Fire;
    public bool Jump;
    public float XVelocity;
    
}
public class P : MonoBehaviour
{

    [Header("打击配置")]
    [SerializeField]
    private GameObject HitCon;
    [Header("红")]
    [SerializeField]
    private Vector2 normalLandHitOffset = new Vector2(1,0);
    [SerializeField]
    private Vector2 normalLandHitSize = new Vector2(1,0.25f);
    
    [Header("黄色")]
    [SerializeField]
    private Vector2 normalAirHitOffset = new Vector2(1,0);
    [SerializeField]
    private Vector2 normalAirHitSize = new Vector2(1,0.25f);

    [Header("接触地面投影配置")]
    [SerializeField]
    private Vector2 groundCheckVec;
    [SerializeField]
    private Transform groundCheck;
    [SerializeField]
    private LayerMask whatIsGround;
    [SerializeField]
    public Animator anim;
    [SerializeField]
    public float speed = 1.25f;

    [Header("跳跃配置")]
    [SerializeField]
    private float jumpDurationTime = 0.25f;
    [SerializeField]
    private float jumpInitVelocity = 0.25f;
    [SerializeField]
    private float jumpHoldVelocity = 0.5f;

    [SerializeField]
    private float fallSpeed = 2f;

    private float currPressJumpTime = 0;

    private Rigidbody2D rb;
    private BoxCollider2D cc;

    
    private string IDLE = "idle";
    private string SLOW = "slow";
    private string RUN = "run";
    private string LAND_HIT = "landHit";
    private string AIR_HIT = "airHit";
    private string FALL = "fall";
    private string FALLING = "falling";
    private string JUMP_UP = "jumpUp";

    /// 通过玩家输入的速度
    private Vector2 faceDir = Vector2.right;

    private string stateName = "";
    private void Awake() {
        Change2State(FALLING);
    }

    private void Change2State(string stateName) {
        this.stateName = stateName;
        anim.Play(stateName, 0, 0);
        // anim.Play(stateName, 0);
        Debug.Log("当前状态,播放动画"+stateName);
    }

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        cc = GetComponent<BoxCollider2D>();
    }

    public void Reset() {
        transform.position = new Vector3(0f,7,0);
        // GetComponent<Collider2D>().isTrigger = ;
        isDead = false;
        Change2State(IDLE);
    }

    PlayerInput playerInput;
    /// <summary>
    /// 收集输入
    /// </summary>
    void GatherInput() {
        playerInput.Fire = Input.GetButton("Fire1");
        playerInput.Jump = Input.GetKey(KeyCode.Space);
        playerInput.XVelocity = 0;
        if (Input.GetKey(KeyCode.A)) {
            playerInput.XVelocity += -speed;
        }
        if (Input.GetKey(KeyCode.D)) {
            playerInput.XVelocity += speed;
        }
    }

    // Update is called once per frame
    void Update()
    {
        if (isDead)
            return;
        GatherInput();
        
        if (stateName == IDLE || stateName == SLOW) {
            //优先接受攻击输入
            if (playerInput.Fire) {
                Change2State(LAND_HIT);
                return;
            }

            if (playerInput.XVelocity != 0) {
                Change2State(RUN);
                rb.velocity = new Vector2(playerInput.XVelocity, 0);
                SetFaceByXV();
            }
            else {
                if (playerInput.Jump) {
                    Change2State(JUMP_UP);
                    currPressJumpTime = 0;
                    rb.velocity = new Vector2(0, rb.velocity.y + jumpInitVelocity);//初始给跳跃方向的速度
                }
            }
        }

        if (stateName == RUN) {
            if (playerInput.Fire) {//优先接受攻击输入
                Change2State(LAND_HIT);
                rb.velocity = Vector2.zero;
                return;
            }

            if (playerInput.Jump) {//其次接受跳跃输入
                JumpHandle();
                return;
            }

            if (playerInput.XVelocity == 0) {
                Change2State(SLOW);
            }
            else {
                SetFaceByXV();
            }
            rb.velocity = new Vector2(playerInput.XVelocity, rb.velocity.y);

        }

        if (stateName == JUMP_UP || stateName == FALL || stateName == FALLING) {
            if (playerInput.Fire) {//优先接受攻击输入
                Debug.Log("Fire press");
                Change2State(AIR_HIT);
            }
        }
    
    }

    private void JumpHandle() {
        Change2State(JUMP_UP);
        currPressJumpTime = 0;
        if (playerInput.XVelocity == 0) {
            rb.velocity = new Vector2(0, jumpInitVelocity);//给跳跃方向的速度
        }
        else {
            rb.velocity = new Vector2(playerInput.XVelocity, jumpInitVelocity);//给跳跃方向的速度
        }
    }


    /// <summary>
    /// 物理update主要处理，物理信息变化方面的操作，比如速度变成0，然后受重力下落之类的
    /// </summary>
    private void FixedUpdate() {
        if (isDead)
            return;

        var stateInfo = anim.GetCurrentAnimatorStateInfo(0);
        rb.velocity = new Vector2(playerInput.XVelocity, rb.velocity.y - fallSpeed * Time.fixedDeltaTime);

        if (stateName == IDLE || stateName == RUN) {
            if (rb.velocity.y < 0) {
                Change2State(FALL);
            }
        }

        if (stateName == JUMP_UP) {

            SetFaceByXV();
            currPressJumpTime += Time.deltaTime;
            if (playerInput.Jump && currPressJumpTime < jumpDurationTime) {//当按下跳跃键，同时按下跳跃时间没超过【跳跃上升时间】
                rb.velocity = new Vector2(playerInput.XVelocity, rb.velocity.y + jumpHoldVelocity);//持续给跳跃方向的速度
            }
            else {
                currPressJumpTime = jumpDurationTime;
            }

            if (rb.velocity.y < 0) {
                Change2State(FALL);
            }
        }

        if (stateName == FALL || stateName == FALLING) {

            SetFaceByXV();
            // 检查是否触地
            if (IsStandGround()) {
                //落地
                Debug.Log("落地啦！");
                if (playerInput.XVelocity == 0) {
                    Change2State(IDLE);
                }
                else {
                    Change2State(RUN);
                }
            }
        }

        if (stateName == AIR_HIT) {
            if (IsStandGround()) {
                //落地
                Debug.Log("落地啦！");
                if (playerInput.XVelocity == 0) {
                    Change2State(IDLE);
                }
                else {
                    Change2State(RUN);
                }
            }
        }
    }  

    private bool IsStandGround() {
        return Physics2D.OverlapBox(groundCheck.position, groundCheckVec,0, whatIsGround);
    }

    private void SetFace(Vector2 dir)
    {
        if (faceDir != dir) {
            transform.Rotate(0.0f, 180.0f, 0.0f);
            faceDir = dir;
        }
    }
    ///通过X方向速度V来设置face
    private void SetFaceByXV()
    {
        if (playerInput.XVelocity == 0)
            return;
        if (playerInput.XVelocity > 0) {
            SetFace(Vector2.right);
        }
        else {
            SetFace(Vector2.left);
        }
    }


    #region 屏幕抖动处理
    private bool isDead = false;
    private System.Threading.CancellationTokenSource cts;
    public void PlayDie() {
        isDead = true;
        rb.velocity = Vector2.zero;
        // GetComponent<Collider2D>().isTrigger = true;
        StartCoroutine(Shake());
    }
    
    Vector3 originPos;
    private static int SHAKE_TOTAL_TIMES = 30;
    private static int shakeTimes = 0;
    IEnumerator Shake() {
        originPos = transform.position;
        shakeTimes=0;
        while (true) {
            transform.position = new Vector3(originPos.x + UnityEngine.Random.Range(-0.15f, 0.15f), originPos.y + UnityEngine.Random.Range(-0.15f, 0.15f), transform.position.z);
            yield return new WaitForEndOfFrame();
            shakeTimes++;
            if (shakeTimes >= SHAKE_TOTAL_TIMES) {
                transform.position = originPos;
                originPos = transform.position;
                break;
            }
        }
        yield return new WaitForSeconds(0.2f);

        Material material = GetComponent<Renderer>().sharedMaterial;
        DOTween.To(() => material.GetFloat("_Fade"), x => material.SetFloat("_Fade", x), 0, 1.0f);
        yield return new WaitForSeconds(1f);
        
        //GameUI.ComMain.Instance.ComGameOver.visible = true;
    }

    #endregion


    #region Gizmos
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireCube(groundCheck.position, groundCheckVec);
    }

    private void OnDrawGizmosSelected() {
        Gizmos.color = Color.red;
        Gizmos.DrawWireCube(normalLandHitOffset, normalLandHitSize);
        
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireCube(normalAirHitOffset, normalAirHitSize);
    }
    #endregion



    #region 帧事件

    private void HitHandle(RaycastHit2D hit) {
        //Main.GenDamageNumber(Random.Range(10,99), hit.point);
    
        ////红闪
        //Sequence mySequence = DOTween.Sequence();
        //mySequence.Append(hit.transform.GetComponent<SpriteRenderer>().DOColor(Color.red, 0.1f));
        //mySequence.Append(hit.transform.GetComponent<SpriteRenderer>().DOColor(Color.white, 0.1f));

        //if (Main.HitPrefab) {
        //    var hitEffect = GameObject.Instantiate<GameObject>(Main.HitPrefab);
        //    hitEffect.transform.position = hit.point;
        //}
    }

    public void OnFrameLandHit() {
        var hitArr = Physics2D.BoxCastAll(transform.position + new Vector3(normalLandHitOffset.x * faceDir.x, normalLandHitOffset.y, 0), normalLandHitOffset,0, faceDir, normalLandHitOffset.x, 1 << LayerMask.NameToLayer("EnemyHitBy"));
        for (int i = 0; i < hitArr.Length; i++)
        {
            HitHandle(hitArr[i]);
        }                                                                         
    }
    public void OnFrameLandHitAnimOver() {
        //以后可能要做是否 在地面的测试 现在暂时不
        if (playerInput.Fire) {
            Change2State(LAND_HIT);
        }
        else if (playerInput.Jump) {
            JumpHandle();
        }
        else if (playerInput.XVelocity == 0) {
            Change2State(IDLE);
        }
        else {
            Change2State(RUN);
        }
    }

    public void OnFrameAirHit() {
        var hitArr = Physics2D.BoxCastAll(transform.position + new Vector3(normalAirHitOffset.x * faceDir.x, normalAirHitOffset.y, 0), normalAirHitSize,0, faceDir, normalAirHitSize.x, 1 << LayerMask.NameToLayer("EnemyHitBy"));
        for (int i = 0; i < hitArr.Length; i++)
        {
            HitHandle(hitArr[i]);
        }  
    }
    public void OnFrameAirHitOver() {
    }
    public void OnAirHitOver() {
        if (rb.velocity.y > 0) {
            Change2State(JUMP_UP);
        }
        else {
            Change2State(FALL);
        }
    }

    public void OnFallAnimOver() {
        Change2State(FALLING);
    }
    public void OnSlowAnimOver() {
        Change2State(IDLE);
    }
    #endregion

}
